﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using System.Net.Sockets;

namespace collabr8
{
    public sealed class Session
    {
        // This hash table stores users and connections (browsable by user)
        private static Hashtable users = new Hashtable(4); // 4 users at one time limit
        // This hash table stores messages (chat + control) connections and users (browsable by connection)
        private static Hashtable connections = new Hashtable(4);
        private static ArrayList videoConnections = new ArrayList(4);
        private static ArrayList clipConnections = new ArrayList(4);
        private static ArrayList ConnectionHandlers = new ArrayList(4);
        private static ArrayList ClipConnectionHandlers = new ArrayList(4);
        private static readonly Session instance = new Session();
        private Session() { }

        public static Session Current
        {
            get 
            {
                return instance; 
            }
        }

        public void AddConnection(TcpClient tcpUser, string strUsername)
        {
            users.Add(strUsername, tcpUser);
            connections.Add(tcpUser, strUsername);
        }

        public void AddConnectionHandler(Connection c)
        {
            ConnectionHandlers.Add(c);
        }

        public void AddVideoConnection(TcpClient client)
        {
            if (!videoConnections.Contains(client))
                videoConnections.Add(client);
        }

        public void AddClipConnection(TcpClient client)
        {
            if (!clipConnections.Contains(client))
            {
                clipConnections.Add(client);
                ClipConnectionHandlers.Add(new ClipConnection(client));
            }
        }

        public void RemoveVideoConnection(TcpClient client)
        {
            videoConnections.Remove(client);
        }

        public void RemoveClipConnection(TcpClient client)
        {
            clipConnections.Remove(client);
        }

        public void RemoveConnection(TcpClient tcpUser)
        {            
            users.Remove(connections[tcpUser]);
            connections.Remove(tcpUser);
        }

        public void RemoveConnection(string strUsername)
        {
            connections.Remove(users[strUsername]);
            users.Remove(strUsername);
        }

        public void ClearVideoConnections()
        {
            for (int i = 0; i < videoConnections.Count; i++)
            {
                if (videoConnections[i] != null)
                    ((TcpClient)videoConnections[i]).Close();
            }

            videoConnections.Clear();
        }

        public void End()
        { 
            for (int i = 0; i < connections.Count; i++)
            {
                if(connections[i] != null)
                    ((TcpClient)connections[i]).Close();
            }
            for (int i = 0; i < clipConnections.Count; i++)
            {
                if (clipConnections[i] != null)
                    ((TcpClient)clipConnections[i]).Close();
            }
            for (int i = 0; i < videoConnections.Count; i++)
            {
                if (videoConnections[i] != null)
                    ((TcpClient)videoConnections[i]).Close();
            }

            connections.Clear();
            users.Clear();
            videoConnections.Clear();
            clipConnections.Clear();
            ConnectionHandlers.Clear();
            ClipConnectionHandlers.Clear();
        }


        public String UserByConnection(TcpClient tcpUser)
        {
            return (String)connections[tcpUser];
        }

        public TcpClient ConnectionByUser(String strUsername)
        {
            return (TcpClient)users[strUsername];
        }

        public bool HasUser(String strUsername)
        {
            return users.Contains(strUsername) && users[strUsername]!=null;
        }

        public bool HasUser(TcpClient tcpUser)
        {
            return connections.Contains(tcpUser) && connections[tcpUser] != null;
        }

        public bool HasClipUser(TcpClient tcpUser)
        {
            return clipConnections.Contains(tcpUser);
        }

        public int Count
        {
            get
            {
                return users.Count;
            }
        }

        public int VideoCount
        {
            get
            {
                return videoConnections.Count;
            }
        }

        public int ClipCount
        {
            get
            {
                return clipConnections.Count;
            }
        }

        public TcpClient[] Clients
        {
            get
            {
                // Create an array of TCP clients, the size of the number of users we have
                TcpClient[] tcpClients = new TcpClient[users.Count];
                // Copy the TcpClient objects into the array
                users.Values.CopyTo(tcpClients, 0);
                return tcpClients;
            }
        }

        public TcpClient[] VideoClients
        {
            get
            {
                // Create an array of TCP clients, the size of the number of users we have
                TcpClient[] tcpClients = new TcpClient[videoConnections.Count];
                // Copy the TcpClient objects into the array
                videoConnections.CopyTo(tcpClients, 0);
                return tcpClients;
            }
        }

        public TcpClient[] ClipClients
        {
            get
            {
                // Create an array of TCP clients, the size of the number of users we have
                TcpClient[] tcpClients = new TcpClient[clipConnections.Count];
                // Copy the TcpClient objects into the array
                clipConnections.CopyTo(tcpClients, 0);
                return tcpClients;
            }
        }
    }
}
